import string

import objects

variables = {
	"objects": objects.names,

	"directions": {
		"random": -1,
		"right": 0,
		"down": 1,
		"left": 2,
		"up": 3,
	},

	"states": {
		"open": True,
		"closed": False,
	},
	
	"fake wall": {
		"fake": True,
		"real": False,
	},
	
	"misc": {
		"float": True,
	},
	
	"custom": {},
}

class ParseError(Exception): pass
class IncompatibleArguments(ParseError): pass
class MismatchedBrackets(ParseError): pass
class MismatchedQuotes(ParseError): pass

def parse(text, variables):
	if text.count('(') != text.count(')'):
		raise MismatchedBrackets(text)
		
	if text.count('"') % 2:
		raise MismatchedQuotes(text)

	results = []
	
	while text:		
		if text[0] in ', ':
			text = text[1:]
			
			end = 0
			result = None		
		elif text[0] in string.digits or text[0] in "-+":			
			end = text.find(',') + 1
			
			if end == 0:
				end = text.find('#') + 1
				
				if end == 0:
					result = text
					end = len(text)
				else:
					result = text[:end - 1]
			else:
				result = text[:end - 1]
				
			result = int(result)		
		elif text[0] == '(':
			end = text.find(')') + 1
			result = tuple(parse(text[1:end - 1], variables))		
		elif text[0] == '"':		
			end = text[1:].find('"') + 2	
			result = text[1:end - 1]
		else:
			end = text.find(',') + 1
			
			if end == 0:
				end = text.find('#') + 1
				
				if end == 0:
					variable = text
					end = len(text)
				else:
					variable = text[:end - 1]
			else:
				variable = text[:end - 1]
			
			variable = variable.lower()
			
			for name, vars in variables.iteritems():
				if variable in vars:
					result = vars[variable]
					break
			
		if result is not None:
			results.append(result)	
		
		text = text[end:]
		
	return results
	
def parse_object(map, text, variables):
	if "<-" in text.split(":", 1)[0]:
		variable, text = [part.strip() for part in text.split("<-")]
	else:
		variable = None
	
	type_name, arguments = text.split(":", 1)
	
	type = variables["objects"][type_name]
	args = parse(arguments, variables)
	
	try:
		object = type(map, *args)
		
		if variable:
			variables["custom"][variable] = object
		
		return object
	except TypeError:
		msg = "'%s' object does not take arguments in the form '%s'" % (
			type_name, str(arguments))
			
		raise IncompatibleArguments(msg)
